<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <script>
            // 构造函数通过原型 分配的属性和方法，可以被所有实例对象共享
            // 原型：构造函数的一个属性，指向一个对象，这个对象包含了所有实例对象共享的属性和方法
            // 原型对象：prototype 原型对象的this指向构造函数的实例对象，和构造函数的this相同

            function Person(username, age) {
                this.username = username;
                this.age = age;
            }
            // 通过原型分配属性和方法
            Person.prototype.sayHello = function() {
                console.log('hello');
            }
            const person = new Person('pink', 18);
            person.sayHello(); // 使用的时候直接调用，不用prototype

            // 实例对象可以新增方法或者覆盖原型对象的方法
            person.sayHi = function() {
                console.log('hi');
            }
            person.sayHello = function() {
                console.log('new hello');
            }
            person.sayHi();
            person.sayHello(); // new hello

            // constructor属性
            // 每个原型对象都有一个constructor属性，指向构造函数
            console.log(Person.prototype.constructor === Person); // true
            // 使用场景：给原型对象赋值时可以指定constructor属性
            Person.prototype = {
                constructor: Person,  // 指定constructor属性
                sayHello: function() {
                    console.log('hello');
                }
            }


            // __proto__ 是每个实例对象都有的属性，指向构造函数的原型对象，这样可以使用原型对象的属性和方法
            console.log(person.__proto__ === Person.prototype); // true
            // 原型对象 还有 __proto__ 属性，指向Object.prototype，而Object.prototype.__proto__ 是 null
            console.log(Object.prototype.__proto__ === null); // true
            
            
            // 原型链：查找属性和方法的过程，先在实例对象中查找，再在原型对象中查找，再在原型对象的原型对象中查找，直到Object.prototype.__proto__ 为null
            // instanceof 运算符：判断一个构造函数的原型对象是否在实例对象的原型链上
        
        </script>

    </body>
</html>